#include <QDebug>
#include <QtGlobal>
#include "gl_widget.h"

#define PARTICLE_NUM_PER_SHOOT 1
#define TIMER_DELAY 10

GLWidget::GLWidget(QWidget *parent)
    : QOpenGLWidget(parent) {

    m_elapsedTimer.start();
    connect(&m_timer, &QTimer::timeout, this, &GLWidget::animate);
    m_timer.start(TIMER_DELAY);
}

GLWidget::~GLWidget() {
    m_timer.stop();
    makeCurrent();
    delete m_particleDrawer;
    delete m_particleShaderProgram;
    delete m_particleSystem;
    delete m_redShooter;
    delete m_greenShooter;
    delete m_blueShooter;
    doneCurrent();
}

void GLWidget::animate() {
    float currentTime = m_elapsedTimer.elapsed() / 1000.f;
    m_redShooter->addParticles(m_particleSystem
            , currentTime
            , PARTICLE_NUM_PER_SHOOT);
    m_greenShooter->addParticles(m_particleSystem
            , currentTime
            , PARTICLE_NUM_PER_SHOOT);
    m_blueShooter->addParticles(m_particleSystem
            , currentTime
            , PARTICLE_NUM_PER_SHOOT);
    update();
}

void GLWidget::initializeGL() {
    initializeOpenGLFunctions();

    glClearColor(0.f, 0.f, 0.f, 1.0f);
    glEnable(GL_PROGRAM_POINT_SIZE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    // 必须enable这个才能正确绘制点精灵
    glEnable(GL_POINT_SPRITE_ARB);

    m_particleShaderProgram = new ParticleShaderProgram(
            ":glsl/particle_shader.vert"
            , ":glsl/particle_shader.frag");

    m_particleSystem = new ParticleSystem(100000);
    QVector3D position{-1.f, 0.f, 0.f};
    QVector3D color{1.f, 0.f, 0.f};
    QVector3D direction{0.f, 0.5f, 0.f};
    m_redShooter = new ParticleShooter(position, color, direction, 5.0);

    position.setX(0.f);
    color.setX(0.f);
    color.setY(1.f);
    m_greenShooter = new ParticleShooter(position, color, direction, 5.0);

    position.setX(1.f);
    color.setY(0.f);
    color.setZ(1.f);
    m_blueShooter = new ParticleShooter(position, color, direction, 5.0);

    m_particleDrawer = new ParticleDrawer(m_particleShaderProgram, m_particleSystem);
}

void GLWidget::resizeGL(int w, int h) {
    // 完成model view project矩阵的设置
    QMatrix4x4 projMat;
    projMat.setToIdentity();
    projMat.perspective(45, (float)w/h, 1, 10);

    QMatrix4x4 viewMat;
    viewMat.setToIdentity();
    QVector3D to{0.f, -0.15f, -5.f};
    viewMat.translate(to);

    QMatrix4x4 modelMat;
    modelMat.setToIdentity();
    m_particleDrawer->setMatrix(projMat * viewMat * modelMat);
}

void GLWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);

    float currentTime = m_elapsedTimer.elapsed() / 1000.f;
    m_particleDrawer->setCurrentTime(currentTime);
    m_particleDrawer->draw();
}
